/*
    BibleNotebook - A bible reader software
    Copyright (C) 2014  Williams Fernando Lopez

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
 */

/*
 * DialogInstallBibles.java
 * Williams Lopez
 * Created on Oct 4, 2013, 11:09:12 AM
 */

package com.simplebible.ui.components;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
import org.crosswire.jsword.book.sword.ConfigEntryType;
import org.crosswire.jsword.book.sword.SwordBookMetaData;
import com.simplebible.bible.BibleReader;
import com.simplebible.bible.BibleUtils;
import com.simplebible.Main;
import wl.util.TextResourcesUtil;
import wl.util.Utils;
import com.simplebible.dictionary.DictionaryUtils;
import com.simplebible.dictionary.IDictionary;
import com.simplebible.bible.objects.Bible;
import com.simplebible.objects.Preferences;
import com.simplebible.support.sword.FromSwordConverter;

/**
 *
 * @author Williams Lopez
 */
public class DialogInstallBibles extends javax.swing.JDialog {

    JFileChooser fileChooser;

    /** Creates new form DialogInstallBibles */
    public DialogInstallBibles(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        //this.setUndecorated(true);
        this.setLocation(parent.getLocation().x+100,parent.getLocation().y+100);
        initComponents();
        fileChooser = new JFileChooser();
        fileChooser.addChoosableFileFilter(new FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.getName().toLowerCase().endsWith(".zip") || f.isDirectory();
            }

            @Override
            public String getDescription() {
                return "SWord \"bible/dictionary file\"";
            }
        });
        fileChooser.addChoosableFileFilter(new FileFilter() {

            @Override
            public boolean accept(File f) {
                return f.getName().endsWith(".sb") || f.isDirectory();
            }

            @Override
            public String getDescription() {
                return "BibleNotebook \"bible file\"";
            }
        });

        
        refresh();
    }

    public final void refresh(){
        try{
            

            jList1.clearSelection();
            DefaultListModel model = new DefaultListModel();

            List<Bible> bibles = BibleReader.getVersions();
            for(Bible b: bibles){
                model.addElement(b);
            }
            List<IDictionary> dicts = DictionaryUtils.getDictionaries();
            for(IDictionary dict: dicts){
                model.addElement(dict);
            }

            jList1.setModel(model);
        }catch(Exception e){
            MainPanel.showNotification("generic_error", e);
        }
    }

    public void cerrar(){
        try{
        if(BibleReader.getVersions().isEmpty()){
            JOptionPane.showMessageDialog(this, TextResourcesUtil.getText("instalar_una_biblia"));
            System.exit(0);
        }else{
            this.dispose();
        }
        }catch(Exception e){
            Utils.printToLog("Error al cerrar el dialogo de instalacion "+e.getMessage(), e, Preferences.LOG_LEVEL_ERROR);
            MainPanel.showNotification("generic_error", e);
        }
    }

    public void eliminar(){
        try{
            
            if (jList1.getSelectedValue() == null) {
                MainPanel.showNotification("seleccione_una_biblia", null);
                return;
            }


            MainPanel.showNotification("eliminando_biblia_dic", null, NotificationPane.TYPE_WAITING);

            if (jList1.getSelectedValue() instanceof Bible) {
                Bible selected = (Bible) jList1.getSelectedValue();
                String text = TextResourcesUtil.getText("confirmar_eliminacion_biblia");
                text = text.replace("%1", selected.getHumanName());

                int res = JOptionPane.showConfirmDialog(this, text, "Confirm", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (res != JOptionPane.YES_OPTION) {
                    return;
                }

                if(!BibleUtils.removeBible(selected.getAbreviation().getBible())){
                    MainPanel.showNotification("no_pudo_eliminar_biblia", null);
                }
            }else{
                IDictionary selected = (IDictionary) jList1.getSelectedValue();
                String text = TextResourcesUtil.getText("confirmar_eliminacion_biblia");
                text = text.replace("%1", selected.getDictionaryName());

                int res = JOptionPane.showConfirmDialog(this, text, "Confirm", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (res != JOptionPane.YES_OPTION) {
                    return;
                }

                if(!DictionaryUtils.removeDictionary(selected)){
                    MainPanel.showNotification("no_pudo_eliminar_biblia", null);
                }
            }


            

        }catch (Exception e) {
            Utils.printToLog("Error al desinstalar la biblia "+e.getMessage(), e, Preferences.LOG_LEVEL_ERROR);
            MainPanel.showNotification("generic_error", e);
        }

        try {
            Thread.currentThread().sleep(500);
        } catch (Exception ex) {
        }
        refresh();
        Main.refreshUI();
        MainPanel.showNotification("deleted_successfully", null);
    }


    public void install(){

        try {
            fileChooser.setMultiSelectionEnabled(false);

            int res = fileChooser.showOpenDialog(this);

            if (res != JFileChooser.APPROVE_OPTION) {
                return;
            }

            File file = fileChooser.getSelectedFile();

            if (!file.exists() || !file.canRead()) {
                MainPanel.showNotification("cant_read_file", null);
                return;
            }

            boolean swordFile = file.getName().toLowerCase().endsWith(".zip");
            if(swordFile){
                processSwordFile(file);
            }else{
                processSimpleBible(file);
            }
            

            

        } catch (Exception e) {
            Utils.printToLog("Error la instalar biblia "+e.getMessage(), e, Preferences.LOG_LEVEL_ERROR);
            MainPanel.showNotification("generic_error", e);
        }

    }

    private void processSwordFile(File file ) throws Exception{

        final File ffile = file;


        if (!file.exists()) {
            throw new Exception("File not found");
        }

        new Thread(){
            @Override
            public void run() {

                File rootOut = null;
                

                try{


                    rootOut = Utils.extractFolder(ffile.getAbsolutePath());
                    File configs = new File(rootOut.getAbsolutePath() + File.separator + "mods.d");

                    if (!configs.exists()) {
                        throw new Exception("Config file not found");
                    }

                    File config = configs.listFiles()[0];
                    SwordBookMetaData md = new SwordBookMetaData(Utils.readFile(config), "booksword");
                    String modDrv = (String)md.getProperty(ConfigEntryType.MOD_DRV);
                    if (modDrv.equals("zText")) {
                        processSwordBible(config);
                    } else if (modDrv.equals("RawLD") || (modDrv.equals("zLD"))) {
                        processSwordDict(rootOut);
                    } else {
                        throw new Exception("Mod DRV not supported " + md.getProperty(ConfigEntryType.MOD_DRV));
                    }
                }catch(Exception e){
                    MainPanel.showNotification("generic_error", e);
                    Utils.printToLog("Error al convertir la biblia/diccionario", e, Preferences.LOG_LEVEL_ERROR);
                } finally {
                    Utils.deleteDirectory(rootOut);
                    try {
                        refresh();
                        Main.refreshUI();
                    } catch (Exception ex) {
                        Utils.printToLog("Error al refrescar la aplicacion", ex, Preferences.LOG_LEVEL_ERROR);
                    }
                }
            }
        }.start();

        

    }

    private void processSwordDict(File tmpRootDir) throws Exception {
        File[] content = tmpRootDir.listFiles();
        for(File f:content){
            Utils.copyDirectory(f, new File(IDictionary.root));
        }

        MainPanel.showNotification("dictionary_installed_successfull", null);

//        String finalName = configFile.getName().substring(0, configFile.getName().indexOf('.')).toLowerCase();
//
//        File newDict = new File(IDictionary.root + File.separator + finalName);
//
//        if (newDict.exists()) {
//            int overwriteRes = JOptionPane.showConfirmDialog(this, TextResourcesUtil.getText("biblia_existe_confirmar"), TextResourcesUtil.getText("biblia_existe"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
//            if (overwriteRes != JOptionPane.YES_OPTION) {
//                return;
//            }
//            eliminar();
//        }
//
//
//        FromSwordConverter.swordToSimpleDict(configFile, new File(IDictionary.root + File.separator + finalName), new ActionListener() {
//
//            public void actionPerformed(ActionEvent e) {
//                String str = TextResourcesUtil.getText("proceso_tomara_unos_minutos") + "<br/>";
//                int messageType = NotificationPane.TYPE_WAITING;
//                if (e.getID() == 100) {
//                    messageType = NotificationPane.TYPE_INFO;
//                    str = "";
//                }
//
//                str += e.getActionCommand() + "<br/>";
//                str += "<b>!" + e.getID() + "% completed</b>";
//                MainPanel.showNotification(str, null, messageType);
//            }
//        });

        DictionaryUtils.cleanDictionaryCache();
    }

    private void processSwordBible(File configFile) throws Exception {


        String finalName = configFile.getName().substring(0, configFile.getName().indexOf('.')).toLowerCase();
        File newBible = new File(BibleReader.root + File.separator + finalName);

        if (newBible.exists()) {
            int overwriteRes = JOptionPane.showConfirmDialog(this, TextResourcesUtil.getText("biblia_existe_confirmar"), TextResourcesUtil.getText("biblia_existe"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
            if (overwriteRes != JOptionPane.YES_OPTION) {
                return;
            }
        }


        FromSwordConverter.swordToSimpleBible(configFile, newBible, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                String str = TextResourcesUtil.getText("proceso_tomara_unos_minutos") + "<br/>";
                int messageType = NotificationPane.TYPE_WAITING;
                if (e.getID() == 100) {
                    messageType = NotificationPane.TYPE_INFO;
                    str = "";
                }

                str += e.getActionCommand() + "<br/>";
                str += "<b>!" + e.getID() + "% completed</b>";
                MainPanel.showNotification(str, null, messageType);
            }
        });

        BibleReader.cleanBiblesCache();

    }

    private void processSimpleBible(File file) throws Exception{
        ZipInputStream zi = new ZipInputStream(new FileInputStream(file));

            ZipEntry zie;
            byte[] buff = new byte[500000];

            boolean overwriteConfirmed = false;

            while((zie = zi.getNextEntry())!=null){
                File fileOut = new File("bibles"+File.separator+zie.getName());


                if(!overwriteConfirmed){
                    if(fileOut.exists()){
                        int overwriteRes = JOptionPane.showConfirmDialog(this, TextResourcesUtil.getText("biblia_existe_confirmar"), TextResourcesUtil.getText("biblia_existe"), JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE);
                        if(overwriteRes != JOptionPane.YES_OPTION){
                            return;
                        }
                        overwriteConfirmed = true;
                    }
                }

                FileOutputStream fos = new FileOutputStream(fileOut);
                int len;
                while ((len = zi.read(buff)) > 0) {
                    fos.write(buff, 0, len);
                }
                fos.close();
            }
            zi.close();

        BibleReader.cleanBiblesCache();
        refresh();
        Main.refreshUI();
    }

    public void mostrarInfo(){
        if (jList1.getSelectedValue() == null) {
            MainPanel.showNotification("seleccione_una_biblia", null);
            return;
        } else if (jList1.getSelectedValue() instanceof Bible) {
            InfoViewerDialog.showDialog((Bible) jList1.getSelectedValue());
        } else if (jList1.getSelectedValue() instanceof IDictionary){
            InfoViewerDialog.showDialog((IDictionary)jList1.getSelectedValue());
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        buttonRemove = new javax.swing.JButton();
        buttonInstall = new javax.swing.JButton();
        buttonClose = new javax.swing.JButton();
        buttonShowBibleInfo = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Bibles/Dictionaries");

        jPanel1.setBackground(new java.awt.Color(255, 255, 255));

        jPanel2.setBackground(new java.awt.Color(255, 255, 255));
        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Biblias instaladas"));

        jScrollPane1.setBorder(null);

        jList1.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jList1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jScrollPane1.setViewportView(jList1);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 617, Short.MAX_VALUE)
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 325, Short.MAX_VALUE)
                .addContainerGap())
        );

        buttonRemove.setText("Eliminar seleccionada");
        buttonRemove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonRemoveActionPerformed(evt);
            }
        });

        buttonInstall.setText("Instalar");
        buttonInstall.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonInstallActionPerformed(evt);
            }
        });

        buttonClose.setText("Cerrar");
        buttonClose.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                buttonCloseMouseClicked(evt);
            }
        });
        buttonClose.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonCloseActionPerformed(evt);
            }
        });

        buttonShowBibleInfo.setText("Mostrar información de biblia");
        buttonShowBibleInfo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonShowBibleInfoActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addComponent(buttonShowBibleInfo)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 175, Short.MAX_VALUE)
                        .addComponent(buttonInstall)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(buttonRemove)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(buttonClose)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonRemove)
                    .addComponent(buttonInstall)
                    .addComponent(buttonClose)
                    .addComponent(buttonShowBibleInfo))
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void buttonCloseMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_buttonCloseMouseClicked
        
    }//GEN-LAST:event_buttonCloseMouseClicked

    private void buttonInstallActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonInstallActionPerformed
        install();
    }//GEN-LAST:event_buttonInstallActionPerformed

    private void buttonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCloseActionPerformed
        cerrar();
    }//GEN-LAST:event_buttonCloseActionPerformed

    private void buttonRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRemoveActionPerformed
        eliminar();
    }//GEN-LAST:event_buttonRemoveActionPerformed

    private void buttonShowBibleInfoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonShowBibleInfoActionPerformed
        mostrarInfo();
    }//GEN-LAST:event_buttonShowBibleInfoActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonClose;
    private javax.swing.JButton buttonInstall;
    private javax.swing.JButton buttonRemove;
    private javax.swing.JButton buttonShowBibleInfo;
    private javax.swing.JList jList1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables

}
